<template>
  <div class="v-editor-input-number-rows g-flex g-ov-hidden">
    <div class="g-flex-1">
      <div
        v-for="(item, index) of inputItems"
        :key="index"
        class="__input-rows-row"
      >
        <el-input-number
          v-model="item.value"
          :controls="false"
          :disabled="row.readonly || isModelDisabled"
          :min="minNum"
          :max="maxNum"
          style="overflow: auto; width: 100%"
          @change="handleInputChange"
          @click="currentInputIndex = index"
        />
      </div>
    </div>

    <div
      v-if="selected && !row.readonly && !isModelDisabled"
      class="_input-rows-operation-btns g-flex-0 g-lh-14 g-pd-4"
    >
      <div>
        <img
          src="statics/icons/propertyOperation/iconadd.png"
          class="g-pointer"
          @click="handleAdd"
        />
      </div>
      <div class="g-m-t-4">
        <img
          src="statics/icons/propertyOperation/iconreduce.png"
          class="g-pointer"
          @click="handleDelete"
        />
      </div>
      <div class="g-m-t-4">
        <img
          src="statics/icons/propertyOperation/iconup.png"
          class="g-pointer"
          @click="handleUp"
        />
      </div>
      <div class="g-m-t-4">
        <img
          src="statics/icons/propertyOperation/icondown.png"
          class="g-pointer"
          @click="handleDown"
        />
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { PropertyRow } from "../../types";
import { modelService } from "@/modules/model/service";
import { ref, computed, watch, reactive, inject, Ref } from "vue";
import { propertyUtil } from "../../PropertyUtil";
import { BusEvent, PropertyDataType } from "@/constants/Enums";
import { debounce } from "lodash-es";
import { arrayEqual } from "@/util/common";
import { MetaclassType } from "@/constants/MetaclassType";
import { JAVA_MAX_INTEGER, JAVA_MIN_INTEGER, MAX_INPUT_NUMBER, MIN_INPUT_NUMBER } from "@/constants/constants";

const isModelDisabled = inject("isModelDisabled") as Ref<boolean>;

const props = defineProps<{
  row: PropertyRow;
  selected?: boolean;
}>();

const inputItems = reactive((props.row.value as (number | undefined)[]).map(it => ({ value: it })));
const currentInputIndex = ref<undefined | number>();
const saveValue = debounce(async () => {
  const dto = propertyUtil.getUpdatePropertyDtoByPropertyRow(props.row, app.activeProject!.id);
  dto.value = inputItems.map(it => it.value);
  if (arrayEqual(dto.value, props.row.value as number[])) {
    return;
  }
  let res = await modelService.updateModelProperty(dto);

  if (res) {
    app.$bus.emit(BusEvent.REFRESH_PROPERTY, props.row.modelId);
  }
}, 50);

const maxNum = computed(() => {
  const metaclass = props.row.valueSpecificationInfo?.metaclass;
  if (metaclass) {
    switch (metaclass) {
      case MetaclassType.LiteralUnlimitedNatural:
      case MetaclassType.LiteralInteger:
        return JAVA_MAX_INTEGER;
      case MetaclassType.LiteralReal:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return;
      default:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MAX_INPUT_NUMBER;
    }
  } else {
    switch (props.row.dataType) {
      case PropertyDataType.INTEGER:
      case PropertyDataType.UNLIMITEDNATURAL:
        return JAVA_MAX_INTEGER;
      case PropertyDataType.REAL:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MAX_INPUT_NUMBER;
      default:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MAX_INPUT_NUMBER;
    }
  }
});

const minNum = computed(() => {
  const metaclass = props.row.valueSpecificationInfo?.metaclass;
  if (metaclass) {
    switch (metaclass) {
      case MetaclassType.LiteralUnlimitedNatural:
        return 0;
      case MetaclassType.LiteralInteger:
        return JAVA_MIN_INTEGER;
      case MetaclassType.LiteralReal:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MIN_INPUT_NUMBER;
      default:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MIN_INPUT_NUMBER;
    }
  } else {
    switch (props.row.dataType) {
      case PropertyDataType.INTEGER:
      case PropertyDataType.UNLIMITEDNATURAL:
        return JAVA_MIN_INTEGER;
      case PropertyDataType.REAL:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MIN_INPUT_NUMBER;
      default:
        // eslint-disable-next-line @typescript-eslint/no-loss-of-precision
        return MIN_INPUT_NUMBER;
    }
  }
});

watch(
  () => props.row.value,
  () => {
    inputItems.splice(0, inputItems.length, ...(props.row.value as number[]).map(it => ({ value: it })));
  }
);

function handleInputChange() {
  saveValue();
}

function handleAdd() {
  inputItems.push({ value: 0 });
  currentInputIndex.value = inputItems.length - 1;

  saveValue();
}

function handleDelete() {
  if (currentInputIndex.value === undefined) return;
  inputItems.splice(currentInputIndex.value, 1);
  currentInputIndex.value = undefined;
  saveValue();
}

function handleUp() {
  if (currentInputIndex.value === undefined || currentInputIndex.value === 0) return;
  const cur = inputItems[currentInputIndex.value];
  const pre = inputItems[currentInputIndex.value - 1];
  inputItems[currentInputIndex.value - 1] = cur;
  inputItems[currentInputIndex.value] = pre;
  currentInputIndex.value--;
  saveValue();
}

function handleDown() {
  if (currentInputIndex.value === undefined || currentInputIndex.value === inputItems.length - 1) return;
  const cur = inputItems[currentInputIndex.value];
  const next = inputItems[currentInputIndex.value + 1];
  inputItems[currentInputIndex.value + 1] = cur;
  inputItems[currentInputIndex.value] = next;
  currentInputIndex.value++;
  saveValue();
}
</script>
<style lang="scss" scoped>
.v-editor-input-number-rows {
  display: flex;
  .__input-rows-row {
    border-bottom: 1px solid #ddd;
    height: 27px;
    &:last-of-type {
      border-bottom: none;
    }
  }
  ._input-rows-operation-btns {
    border-left: 1px solid #ddd;
  }
}
._current-row {
  .v-editor-input-number-rows {
    .__input-rows-row {
      &:last-of-type {
        border-bottom: 1px solid #ddd;
      }
    }
  }
}
</style>
